﻿using System;
using System.Collections.Generic;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Storage;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace MapleStory
{
    class Character : Sprite
    {
        const int START_POSITION_X = 125;
        const int START_POSITION_Y = 225;
        const int WIZARD_SPEED = 150;
        const int MOVE_UP = -2;
        const int MOVE_DOWN = 2;
        const int MOVE_LEFT = -1;
        const int MOVE_RIGHT = 1;

        private Texture2D lying;

        private Texture2D standing1;
        private Texture2D standing2;
        private Texture2D standing3;

        private Texture2D walking1;
        private Texture2D walking2;
        private Texture2D walking3;
        private Texture2D walking4;

        enum State
        {
            Walking,
            Jumping,
            Ducking,
            Standing
        }
        State mCurrentState = State.Walking;

        Vector2 mDirection = Vector2.Zero;
        Vector2 mSpeed = Vector2.Zero;

        KeyboardState mPreviousKeyboardState;

        Vector2 mStartingPosition = Vector2.Zero;

        UInt16 WalkingPicture = 1;
        UInt16 StandingPicture = 1;
        double TimeStandStill = 0.0f;

        SpriteEffects WalkingWay = SpriteEffects.None;

        public void LoadContent(ContentManager theContentManager)
        {
            Position = new Vector2(START_POSITION_X, START_POSITION_Y);

            lying = theContentManager.Load<Texture2D>("lying");

            standing1 = theContentManager.Load<Texture2D>("standing1");
            standing2 = theContentManager.Load<Texture2D>("standing2");
            standing3 = theContentManager.Load<Texture2D>("standing3");

            walking1 = theContentManager.Load<Texture2D>("walking1");
            walking2 = theContentManager.Load<Texture2D>("walking2");
            walking3 = theContentManager.Load<Texture2D>("walking3");
            walking4 = theContentManager.Load<Texture2D>("walking4");

            Source = new Rectangle(0, 0, 45, 68);
        }

        #region "Update"

        public void Update(GameTime theGameTime)
        {
            KeyboardState aCurrentKeyboardState = Keyboard.GetState();

            UpdateTexture(theGameTime);

            UpdateMovement(aCurrentKeyboardState);
            UpdateJump(aCurrentKeyboardState);
            UpdateDuck(aCurrentKeyboardState);

            mPreviousKeyboardState = aCurrentKeyboardState;

            base.Update(theGameTime, mSpeed, mDirection);
        }

        private void UpdateMovement(KeyboardState aCurrentKeyboardState)
        {
            if (State.Walking == mCurrentState || State.Standing == mCurrentState)
            {
                mSpeed = Vector2.Zero;
                mDirection = Vector2.Zero;

                if (aCurrentKeyboardState.IsKeyDown(Keys.Left) == true)
                {
                    mSpeed.X = WIZARD_SPEED;
                    mDirection.X = MOVE_LEFT;
                    mCurrentState = State.Walking;
                    WalkingWay = SpriteEffects.None;
                }
                else if (aCurrentKeyboardState.IsKeyDown(Keys.Right) == true)
                {
                    mSpeed.X = WIZARD_SPEED;
                    mDirection.X = MOVE_RIGHT;
                    mCurrentState = State.Walking;
                    WalkingWay = SpriteEffects.FlipHorizontally;
                }
                else mCurrentState = State.Standing;

            }
        }

        private void UpdateJump(KeyboardState aCurrentKeyboardState)
        {
            if (State.Walking == mCurrentState || State.Standing == mCurrentState)
            {
                if (aCurrentKeyboardState.IsKeyDown(Keys.Space) == true && mPreviousKeyboardState.IsKeyDown(Keys.Space) == false)
                {
                    Jump();
                }
            }

            if (mCurrentState == State.Jumping)
            {
                if (mStartingPosition.Y - Position.Y > 80 && mDirection.Y == MOVE_UP)
                {
                    mSpeed.Y -= (mStartingPosition.Y - Position.Y / 6);
                }

                if (mStartingPosition.Y - Position.Y > 100)
                {
                    mDirection.Y = MOVE_DOWN;
                }

                if (Position.Y > mStartingPosition.Y)
                {
                    Position.Y = mStartingPosition.Y;
                    mCurrentState = State.Standing;
                    mDirection = Vector2.Zero;
                }

                if (aCurrentKeyboardState.IsKeyDown(Keys.Left) == true)
                {
                    mSpeed.X = WIZARD_SPEED;
                    mDirection.X = MOVE_LEFT;
                    WalkingWay = SpriteEffects.None;
                }
                else if (aCurrentKeyboardState.IsKeyDown(Keys.Right) == true)
                {
                    mSpeed.X = WIZARD_SPEED;
                    mDirection.X = MOVE_RIGHT;
                    WalkingWay = SpriteEffects.FlipHorizontally;
                }
            }
        }

        private void Jump()
        {
            if (mCurrentState != State.Jumping)
            {
                mCurrentState = State.Jumping;
                mStartingPosition = Position;
                mDirection.Y = MOVE_UP;
                mSpeed = new Vector2(WIZARD_SPEED, WIZARD_SPEED);
            }
        }

        private void UpdateDuck(KeyboardState aCurrentKeyboardState)
        {
            if (aCurrentKeyboardState.IsKeyDown(Keys.Down) == true)
            {
                Duck();
            }
            else
            {
                StopDucking();
            }
        }

        private void Duck()
        {
            if (State.Walking == mCurrentState || State.Standing == mCurrentState)
            {
                mSpeed = Vector2.Zero;
                mDirection = Vector2.Zero;
                Source = new Rectangle(0, 0, 64, 40);
                Position.Y += 28;

                mCurrentState = State.Ducking;
            }
        }

        private void StopDucking()
        {
            if (mCurrentState == State.Ducking)
            {
                Source = new Rectangle(0, 0, 45, 68);
                Position.Y -= 28;
                mCurrentState = State.Standing;
            }
        }

        private void UpdateTexture(GameTime theGameTime)
        {
            TimeStandStill += theGameTime.ElapsedGameTime.TotalSeconds;

            if (mCurrentState == State.Standing)
            {
                if (TimeStandStill > 0.8)
                {
                    StandingPicture++;
                    TimeStandStill = 0;
                }
            }

            if (mCurrentState == State.Walking)
            {
                if (TimeStandStill > 0.2)
                {
                    TimeStandStill = 0;
                    WalkingPicture++;
                }
            }

            if (StandingPicture == 4) StandingPicture = 1;
            if (WalkingPicture == 5) WalkingPicture = 1;
            
        }

        #endregion

        private Texture2D GetTexture()
        {
            if (mCurrentState == State.Walking)
            {
                if (WalkingPicture == 1) return walking1;
                if (WalkingPicture == 2) return walking2;
                if (WalkingPicture == 3) return walking3;
                if (WalkingPicture == 4) return walking4;
            }

            if (mCurrentState == State.Standing)
            {
                if (StandingPicture == 1) return standing1;
                if (StandingPicture == 2) return standing2;
                if (StandingPicture == 3) return standing3;
            }

            if (mCurrentState == State.Ducking)
            {
                return lying;
            }

            return walking4;
        }

        //Draw the sprite to the screen
        public new void Draw(SpriteBatch theSpriteBatch)
        {
            theSpriteBatch.Draw(GetTexture(), Position, Source,
                Color.White, 0.0f, Vector2.Zero, Scale, WalkingWay, 0);
        }
    }
}
